#pragma once
#include "Mode.h"
#include "lang/System.h"
#include "crypto/CryptoUtil.h"

namespace yzrilyzr_crypto{
	ECLASS(OFB, public Mode){
	private:
	yzrilyzr_array::ByteArray vector;
	yzrilyzr_array::ByteArray temp;
	void setVector(const yzrilyzr_array::ByteArray & block, u_index off, u_index len){
		yzrilyzr_lang::System::arraycopy(block, off, vector, 0, len);
	}
	public:
	OFB(const yzrilyzr_array::ByteArray & iv){
		this->vector=yzrilyzr_array::ByteArray(iv.length);
		this->temp=yzrilyzr_array::ByteArray(iv.length);
		setVector(iv);
	}
	yzrilyzr_array::ByteArray encrypt(const yzrilyzr_array::ByteArray & block, FAQCipherAlgorithm & algorithm)override{
		temp=algorithm.encrypt(vector);
		setVector(temp);
		CryptoUtil:: xor (block, temp, temp);
		return temp;
	}
	yzrilyzr_array::ByteArray encryptFinal(const yzrilyzr_array::ByteArray & block, FAQCipherAlgorithm & algorithm)override{
		temp=algorithm.encrypt(vector);
		setVector(temp);
		return CryptoUtil::xorMinLength(block, temp, temp);
	}
	yzrilyzr_array::ByteArray decrypt(const yzrilyzr_array::ByteArray & block, FAQCipherAlgorithm & algorithm)override{
		return encrypt(block, algorithm);
	}
	yzrilyzr_array::ByteArray decryptFinal(const yzrilyzr_array::ByteArray & block, FAQCipherAlgorithm & algorithm)override{
		return encryptFinal(block, algorithm);
	}
	void setVector(const yzrilyzr_array::ByteArray & block){
		setVector(block, 0, block.length);
	}
	};
}